﻿<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta http-equiv="Content-Language" content="fr" />
        <meta name="Author" content="Laboratoire Sun - SUPINFO Paris" />
        <meta name="owner" content="labo-sun@supinfo.com" />
        <meta name="Identifier-URL" content="http://www.labo-sun.com/" />
        <meta name="Reply-to" content="labo-sun@supinfo.com" />
        <meta name="revisit-after" content="10 days" />
        <meta name="Robots" content="index, follow" />
        <meta name="Description" content="This article is an initiation to 3D programming with Java. We'll create an object, a pyramid that occupies a certain volume, and then we'll learn how to make it move." />
        <meta name="Publisher" content="Laboratoire Sun - SUPINFO Paris" />
        <meta name="Copyright" content="© 2000-2006 Laboratoire Sun - SUPINFO Paris" />
        <link type="text/css" rel="stylesheet" href="./css/template.css" />
        <link type="text/css" rel="stylesheet" href="./css/SyntaxHighlighter.css" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Learn Java 3D programming - Articles - 1/1 - Java &amp; Solaris by the Sun Technologies SUPINFO Laboratory </title>
        <script language="javascript" src="./js/shInit.js" />
        <script language="javascript" src="./js/shCore.js" />
        <script language="javascript" src="./js/shBrushCpp.js" />
        <script language="javascript" src="./js/shBrushCSharp.js" />
        <script language="javascript" src="./js/shBrushCss.js" />
        <script language="javascript" src="./js/shBrushDelphi.js" />
        <script language="javascript" src="./js/shBrushJava.js" />
        <script language="javascript" src="./js/shBrushJScript.js" />
        <script language="javascript" src="./js/shBrushPhp.js" />
        <script language="javascript" src="./js/shBrushPython.js" />
        <script language="javascript" src="./js/shBrushRuby.js" />
        <script language="javascript" src="./js/shBrushSql.js" />
        <script language="javascript" src="./js/shBrushVb.js" />
        <script language="javascript" src="./js/shBrushXml.js" />
        <keywords>java3D,howto,polygone,cube,Java,GUI,Java SE,decouvrir,la,programmation,3d,en,java,articles,1,1,certification,sun,java,solaris,articles,essentiels,tips,astuces,codes,exemple,tutorial,developpement,jsp,servlet,jdbc,jdo,j2se,j2ee,laboratoire</keywords>
        <author>Imad NABLI</author>
    </head>
    <body>
        <div class="chapter">
            <h2>Introduction</h2>
            <div class="subChapter">
                <p>This article is an initiation to 3D programming with Java.
			We'll create an object, a pyramid that occupies a certain volume, and then we'll learn how to make it move in 
			response of an action from the user or animate it accordingly to a defined time and behavior. Actually, doing 
			"true" 3D would be far more difficult than that : a scene only becomes really impressive and beautiful when 
			we're managing light effects and when the faces of the 3D object have some texture. This article won't cover 
			those last two points but will focus on the base of "simple" 3D objects programming.
	      </p>
                <p>
                    <a href="http://java.sun.com/products/java-media/3D/downloads/index.html" target="_blank">&gt; Download the Java 3D API</a>
                </p>
            </div>
        </div>
        <div class="chapter">
            <div class="subChapter">
                <h3>1. Volumes creation</h3>
                <p>To create a pyramid, we just have to define the triangles forming its surface and to assemble them. Once it's done, it will 
			be easy to work with more complex polygons.
	      </p>
                <p>This chapter's objective is to create a regular pyramid with 4 triangular faces, with a square base. We'll give a different 
			color to each face to easily distinguish them and we'll consider the base like a square divided on its diagonal to 
			form 2 triangles. As a result, the pyramid will be composed of 6 triangles.
	      </p>
                <textarea name="code" class="java" rows="10" cols="59">private void makePyramide() {
					TriangleArray pyramide = new TriangleArray(18, TriangleArray.COORDINATES | TriangleArray.COLOR_3);
					float sommets[] = new float[vertices.length];
					for (int i = 0; i
					&lt; sommets.length; i++)
					sommets[i] = vertices[i] * echelle;
					pyramide.setCoordinates(0, sommets);
					pyramide.setColors(0, couleurs);
					setGeometry(pyramide);
					}</textarea>
                <p>To create a triangle, we need a class that implements the abstract class Shape3D and in this class, we need an array of 3 
			points : one for each summit of the triangle. Now, to create our pyramid, we'll need an array of 18 points from 
			which each group of 3 points will represent the summits of each of our 6 triangles. Then, we'll rotate our pyramid 
			two times to estimate our work with some perspective.
	      </p>
                <p style="TEXT-ALIGN: center" align="center">
                    <img src="images/fig1.jpg" />
                </p>
                <p>
                    <i style="mso-bidi-font-style: normal">
                        <span style="font-size:8pt">
                            Figure 1 : The 3D pyramid, Java applied a Culling Algorithm.
							(
                            <a href="java/MaPyramide.java" target="_blank">
                                &gt;
                                <em>Complete sources of figure 1</em>
                            </a>
                            )
                        </span>
                    </i>
                </p>
                <textarea name="code" class="java" rows="5" cols="59">Transform3D rotate1 = new Transform3D();
					rotate1.rotX(-Math.PI / 9.0f);
					Transform3D rotate2 = new Transform3D();
					rotate2.rotY(Math.PI / 6.0f);
					rotate1.mul(rotate2);</textarea>
                <p>Figure 1 shows that Java3D had automatically applied a Culling Algorythm to our object : we'll see in what consists this process 
			in the next chapter.
	      </p>
            </div>
            <div class="subChapter">
                <h3>2. The Culling: a 3D algorythm</h3>
                <p>If you look at the figure 1 (shown above), one of the triangles composing the pyramid's base (here represented in white) 
			doesn't appear : it isn't drawn by Java. The first thing we'd think of would be that we made an error in the 
			triangle's coordinates. Actually, those are the right coordinates, but we put them in the wrong order. We just 
			revealed one of the aspects of the Java 3D package : the Culling. Applied by default on the created objects, the 
			Culling consists of not drawing the parts of the scene that won't be visible (the back of a character shown by 
			front, for example). The Culling needs the faces to be "oriented" to be correctly applied. So, the coordinates 
			must always respect the trigonometrical sense as used in mathematics.
	      </p>
                <center>
                    <p>
                        <img src="images/fig2trigo.jpg" />
                    </p>
                </center>
                <!-- si possible, refaire la figure -->
                <p>
                    <i style="mso-bidi-font-style: normal">
                        <span style="FONT-SIZE: 8pt">
                            Trigonometrical sens : Always respect this sense to avoid bad surprises
                            <o:p xmlns:o="o" />
                        </span>
                    </i>
                </p>
                <p>Then you must respect this convention if you want to have a full base for the pyramid. To do this, you need to look at the 
			white face in a three dimensional Cartesian system with one of the axes pointing towards you. Then you need to 
			enumerate the points of the summits in the trigonometrical sense (counterclockwise) (figure 2).
			Here is the result once it has been done :
	      </p>
                <p style="TEXT-ALIGN: center" align="center">
                    <img src="images/fig2.jpg" />
                </p>
                <p>
                    <i style="mso-bidi-font-style: normal">
                        <span style="FONT-SIZE: 8pt">
                            Figure 2 : The 3D pyramid, with the white base. (Look at the sources and discard the comments to obtain this result)
                            <o:p xmlns:o="o" />
                        </span>
                    </i>
                </p>
            </div>
        </div>
        <div class="chapter">
            <div class="subChapter">
                <h3>3. Interactions with the 3D object</h3>
                <p>We now will try to animate our object. We'll start with the interactions and then we'll briefly see the object animation. The
			goal of this exercise is to let you try both. One interesting example comes with the Java3D distribution : Gearbox. 
			The animation represents gears constantly rolling and you can use the mouse to change the orientation and the 
			point of view.
	      </p>
                <p>
                    <img src="images/fig3.jpg" />
                </p>
                <p style="TEXT-ALIGN: center" align="center">
                    <i style="mso-bidi-font-style: normal">
                        <span style="FONT-SIZE: 8pt">Figure 3 : GearBox, the might of Java3D</span>
                    </i>
                </p>
                <p>To interact with our object, we must define a behavior when the user, for example, press one keyboard key or click on one
			of the mouse buttons. To do that, we have to extend the Behavior class and our class must respect 3 obligatory 
			rules :
	      </p>
                <p style="MARGIN-LEFT: 36pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
                    <span style="mso-list: Ignore">
                        1)
                        <span style="FONT: 7pt 'Times New Roman'">     </span>
                    </span>
		In the class' constructor, you need to give a reference of the transformations group you'll use.
                </p>
                <p style="MARGIN-LEFT: 36pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
                    <span style="mso-list: Ignore">
                        2)
                        <spa style="FONT: 7pt 'Times New Roman'">     </spa>
                    </span>
		You have to rewrite the initialize() method. It's here that you'll define to what events the class must react.
                </p>
                <p style="MARGIN-LEFT: 36pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
                    <span style="mso-list: Ignore">
                        3)
                        <span style="FONT: 7pt 'Times New Roman'">     </span>
                    </span>
		You have to rewrite the processStimulus() method that is automatically called by Java3D. It's in this method that you need 
			to retrieve the call's origin and answer it while applying the required transformations.
                </p>
                <p style="MARGIN-LEFT: 18pt">
                    Here is an extract from the code of 
                    <a href="java/MaPyramideInteraction.java" target="_blank">&gt;
						MaPyramideInteraction.java</a>
                     :
                </p>
                <p>
                    <textarea name="code" class="java" rows="20" cols="59">public class PyramideBehavior extends Behavior {
						private TransformGroup targetTG;
						private Transform3D rotation = new Transform3D();
						private float angle = 0.0f;
						PyramideBehavior(TransformGroup targetTG) {
						this.targetTG = targetTG;
						}
						public void initialize() {
						this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
						}
						public void processStimulus(Enumeration criteria) {
						angle += 0.1f;
						rotation.rotX(angle);
						targetTG.setTransform(rotation);
						this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
						}
						}</textarea>
                </p>
                <p>Then we need to activate our class by modifying slightly the initialization code of the animation branch (figure 4).</p>
                <p style="TEXT-ALIGN: center" align="center">
                    <img src="images/fig4.jpg" />
                </p>
                <p>
                    <textarea name="code" class="java">TransformGroup tg = new TransformGroup();
						tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
						branche.addChild(tg);
						tg.addChild(new Pyramide(2.0));
						PyramideBehavior behavior = new PyramideBehavior(tg);
						behavior.setSchedulingBounds(new BoundingSphere());
						branche.addChild(behavior);</textarea>
                </p>
                <p>As shown in the figure 4, our Behavior class is integrated in the branch. You must remember two specificities of this code : 
	      </p>
                <p style="MARGIN-LEFT: 36pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
                    <span style="mso-list: Ignore">
                        1)
                        <span style="FONT: 7pt 'Times New Roman'">     </span>
                    </span>
		We must be able to modify our transformations group on the fly. This is done by calling the setCapability method.
                </p>
                <p style="MARGIN-LEFT: 36pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt">
                    <span style="mso-list: Ignore">
                        2)
                        <span style="FONT: 7pt 'Times New Roman'">     </span>
                    </span>
		We must be sure that setSchedulingBounds recieve a BoundingSphere object and that it really defines the space area that 
			will be affected by the transformation.
                </p>
                <p>In our case, we'll use a BoundingSphere. Others solutions are possibles, like using BoundingPolygons. By default, the sphere is 
			centered on the system and has a radius of 1 unit. Consequently, all the scene is modified in our example because 
			all of it is contained withing this sphere. In this first example, we react when any key of the keyboard is pressed 
			to rotate our pyramid on the x-axis. We'll see in the next chapter how to do an exact detail of the events, because 
			Java3D proposes really interesting hi-level classes as you can see in this partial list :
	      </p>
                <p align="center" />
                <table class="MsoTableGrid" id="Table1" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" border="1">
                    <tbody>
                        <tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
                            <td valign="top">
                                <p class="MsoNormal" style="TEXT-ALIGN: center" align="center">
                                    <b style="mso-bidi-font-weight: normal">
                                        Wake-Up Criterias
                                        <o:p xmlns:o="o" />
                                    </b>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="TEXT-ALIGN: center" align="center">
                                    <b style="mso-bidi-font-weight: normal">
                                        Description
                                        <o:p xmlns:o="o" />
                                    </b>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 1">
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">WakeupOnActivation</span>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
				Triggered when the view platform intersect with the
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">bounding area.</span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 2">
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">WakeupOnAWTEvent</span>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered when one or more specific AWT events occur.
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial"></span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 3">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnBehaviorPost
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered when a specific Behavior posts a specific event.
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial"></span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 4">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnCollisionEntry
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered at the first collision between a specific object
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">and any other object of the 				scene.</span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 5">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnCollisionExit
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
				Triggered when the specified object isn't colliding anymore.</span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 6">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnCollisionMovement
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered when the object is moving while colliding.
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial"></span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 7">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnDeactivation
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered when the view platform isn't intersecting
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">with the bounding area anymore.</span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 8">
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        WakeupOnElapsedFrames
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <o:p xmlns:o="o"> </o:p>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal" style="mso-layout-grid-align: none">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">
                                        Triggered when a specific number of frames
                                        <o:p xmlns:o="o" />
                                    </span>
                                </p>
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">have been rendered.</span>
                                </p>
                            </td>
                        </tr>
                        <tr style="mso-yfti-irow: 9; mso-yfti-lastrow: yes">
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">WakeupOnElapsedTime</span>
                                </p>
                            </td>
                            <td valign="top">
                                <p class="MsoNormal">
                                    <span style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Arial">Triggered after a specific number 
				of milliseconds.</span>
                                </p>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <p class="MsoNormal" style="mso-layout-grid-align: none">
                    <b>
                        <span style="FONT-SIZE: 9pt; COLOR: white; FONT-FAMILY: Arial">
                            Wake up criterias
							Description
                            <o:p xmlns:o="o" />
                        </span>
                    </b>
                </p>
            </div>
        </div>
        <div class="chapter">
            <div class="subChapter">
                <h3>Conclusion</h3>
                <p>Java3D programming is accessible to whoever want to deepen its Java knowledge. The java libraries are really completes and 
		you can find many tutorials on the internet. This first initiation must push the reader towards discovering new 3D algorythms, 
		and there are no limits to the objects you can create in 3D. After that comes all work about the textures and the light 
		effects to enhance the aestetics of the rendered scene.
	      </p>
                <p>To go farther:</p>
                <p class="MsoNormal">
                    <span style="mso-tab-count: 1">           </span>
                    <a href="http://www.eteks.com/coursjava/java3D.html" target="_blank">&gt;http://www.eteks.com/coursjava/java3D.html</a>
                </p>
                <p class="MsoNormal">
                    <span style="mso-tab-count: 1">           </span>
                    <a href="http://raphaello.univ-fcomte.fr/IG/Java3D/Java3D.htm" target="_blank">&gt;http://raphaello.univ-fcomte.fr/IG/Java3D/Java3D.htm</a>
                </p>
                <p>
                    <i style="mso-bidi-font-style: normal">
                        <span style="FONT-SIZE: 8pt">
                            Source and bibliography : This tutorial is inspired by an article published in the monthly magazine 
                            <u>Programmez</u>
                            of February 2004
                        </span>
                    </i>
                </p>
            </div>
        </div>
        <div class="chapter">
            <div class="subChapter">
                <h3>5. The animations</h3>
                <p>
                    An animation is defined by a specific behavior : an object is moving by itself. Consequently, the classes managing the 
			animations, called "Interpolators", are all extending the Behavior abstract class. As their name implies, the 
			interpolators perform linear interpolations between 2 extremes, following a rhythm and a direction defined by an 
			Alpha object. The Alpha term, that mustn't be mistook with the one used for the color mixing in other 3D 
			libraries, is used because this class manages a value's variations between 0 and 1, remembering a sine curve's
			behavior. The Alpha class has a lot of uses, it's a sort of metronome for the animation, this animation repeating 
			itself a defined or an undefined number of times. For our example, we'll make our pyramid rotate indefinitely along 
			the vertical axis, it takes 60 seconds to Alpha to go from 0 to 1. Hence we're implicitly defining a rotation speed 
			of 1 turn by minute. Here is the extract of the code of 
                    <a href="java/MaPyramideAnimation.java" target="_blank">&gt;MaPyramideAnimation.java </a>
                    :
                </p>
                <p>
                    <textarea name="code" class="java" rows="20" cols="59">BranchGroup branche = new BranchGroup();
						TransformGroup tg = new TransformGroup();
						tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
						branche.addChild(tg);
						tg.addChild(new Pyramide(2.0));
						//Alpha alpha = new Alpha(-1, 60000);
						Alpha alpha = new Alpha(3, 4000);
						RotationInterpolator ri = new RotationInterpolator(alpha, tg);
						/* //Les lignes suivantes pour une rotation de Pi/4 autour de l’axe
						Transform3D rot = new Transform3D();
						rot.rotX((float)Math.PI/- 4.0f);
						RotationInterpolator ri = new RotationInterpolator(alpha, tg, rot, 0.0f, (float)(2.0*Math.PI));
						*/
						ri.setSchedulingBounds(new BoundingSphere());
						branche.addChild(ri);</textarea>
                </p>
                <p align="center">
                    <img src="images/fig6.jpg" />
                </p>
                <p>Before rotating around the vertical axis, we'll give it a rotation of Pi/4 along the horizontal axis so the scene takes more
			relief. To do that, we'll replace the line when we construct the interpolator by the three lines in comments 
			in the code shown above.</p>
                <p>
                    Since there are hi-level Behavior classes, there also are hi-level interpolation classes that allow us to do chained animations.
		The program 
                    <a href="java/MaPyramideAnimationAxe.java" target="_blank">&gt;MaPyramideAnimationAxe.java</a>
                    shows us an example.
                </p>
                <p class="MsoNormal" style="TEXT-ALIGN: center" align="center">
                    <v:shape xmlns:v="v" id="_x0000_i1026" style="WIDTH: 244.5pt; HEIGHT: 244.5pt" type="#_x0000_t75" />
                </p>
                <p align="center">
                    <img src="images/fig7.jpg" />
                </p>
            </div>
        </div>
        <div class="chapter">
            <div class="subChapter">
                <h3>4. Events management</h3>
                <p>To manage a scene's events, you'll need a good knowledge of the Java documentation related to the AWT events and you'll 
			need to know how to use enumerations. The processStimulus method can be called by one or many criterias, 
			sometimes simultaneously and it's in an enumeration that those criterias will be transmitted as argument to this 
			method. Now, to know what criteria has been used, it's necessary to be able to browse easily through the 
			enumeration. In the case of an AWT criteria, you'll have to know what element(s), simultaneous or not, have been
			the origine of the method call. That's why the criteria object sort those events in an array that you'll also need 
			to browse. Then you'll just have to interrogate each event to know exactly what is happening.</p>
                <p>
                    Here is an extract of the code of 
                    <a href="java/MaPyramideInteractionTouchesSouris.java" target="_blank">&gt;MaPyramideInteractionTouchesSouris.java</a>
                    ,
					in this example, we monitor the keys x, y and z of the keyboard to execute a rotation on 
					the axes of the same name, and one click on one of the mouse buttons reinitialize the 
					position of the pyramid :

                </p>
                <p>
                    <textarea name="code" class="java" rows="40" cols="59">public void processStimulus(Enumeration criteria) {
						WakeupCriterion wakeup;
						AWTEvent[] events;
						AWTEvent event;
						int id;
						while (criteria.hasMoreElements()) {
						wakeup = (WakeupCriterion) criteria.nextElement();
						if (wakeup instanceof WakeupOnAWTEvent) {
						events = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
						for (int i = 0; i
						&lt; events.length; i++) {
						event = events[i];
						id = event.getID();
						if (id == KeyEvent.KEY_PRESSED) {
						switch (((KeyEvent) event).getKeyCode()) {
						case KeyEvent.VK_X :
						anglex += 0.1f;
						rotationx.rotX(anglex);
						break;
						case KeyEvent.VK_Y :
						angley += 0.1f;
						rotationy.rotY(angley);
						break;
						case KeyEvent.VK_Z :
						rotationz.rotZ(anglez);
						anglez += 0.1f;
						break;
						default :
						break;
						}
						// reset de la matrice
						rotation.setIdentity();
						rotation.mul(rotationx);
						rotation.mul(rotationy);
						rotation.mul(rotationz);
						}
						if (id == MouseEvent.MOUSE_PRESSED) {
						if (((MouseEvent) event).getButton() == MouseEvent.BUTTON1) {
						anglex = 0.0f;
						angley = 0.0f;
						anglez = 0.0f;
						rotationx.rotX(anglex);
						rotationx.rotY(angley);
						rotationx.rotZ(anglez);
						rotation.setIdentity();
						}
						}
						}
						}
						}
						targetTG.setTransform(rotation);
						this.wakeupOn(new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK));
						}</textarea>
                </p>
                <p style="TEXT-ALIGN: center" align="center">
                    <i style="mso-bidi-font-style: normal">
                        <span style="FONT-SIZE: 8pt">Figure 5 :
							Rotation along the axes</span>
                    </i>
                </p>
            </div>
        </div>
    </body>
</html>

